import clipboard from "@/utils/clipboard"
import { SingletonFactory } from "@/utils/single"
import MindMap from "simple-mind-map"
import MiniMap from "simple-mind-map/src/plugins/MiniMap.js"
import Watermark from "simple-mind-map/src/plugins/Watermark.js"
import KeyboardNavigation from "simple-mind-map/src/plugins/KeyboardNavigation.js"
import ExportPDF from "simple-mind-map/src/plugins/ExportPDF.js"
import ExportXMind from "simple-mind-map/src/plugins/ExportXMind.js"
import Export from "simple-mind-map/src/plugins/Export.js"
import Drag from "simple-mind-map/src/plugins/Drag.js"
import Select from "simple-mind-map/src/plugins/Select.js"
import AssociativeLine from "simple-mind-map/src/plugins/AssociativeLine.js"
import TouchEvent from "simple-mind-map/src/plugins/TouchEvent.js"
import NodeImgAdjust from "simple-mind-map/src/plugins/NodeImgAdjust.js"
import SearchPlugin from "simple-mind-map/src/plugins/Search.js"
import Painter from "simple-mind-map/src/plugins/Painter.js"
import Formula from "simple-mind-map/src/plugins/Formula.js"
import { getData, storeData, storeConfig } from "@mind/utils/mind-store"
import handleClipboardText from "@mind/utils/handleClipboardText"
import customThemeList from "../customThemes"

MindMap.usePlugin(MiniMap)
  .usePlugin(Watermark)
  .usePlugin(Drag)
  .usePlugin(KeyboardNavigation)
  .usePlugin(ExportPDF)
  .usePlugin(ExportXMind)
  .usePlugin(Export)
  .usePlugin(Select)
  .usePlugin(AssociativeLine)
  .usePlugin(NodeImgAdjust)
  .usePlugin(TouchEvent)
  .usePlugin(SearchPlugin)
  .usePlugin(Painter)
  .usePlugin(Formula)

// 注册自定义主题
customThemeList.forEach((item) => {
  MindMap.defineTheme(item.value, item.theme)
})

function createHtml(svg: string): string {
  return `
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>Markmap Export</title>
    </head>
    <body>
    ${svg}
    </body>
    </html>
  `
}

const EventType = [
  "node_active",
  "data_change",
  "view_data_change",
  "back_forward",
  "node_contextmenu",
  "node_click",
  "draw_click",
  "expand_btn_click",
  "svg_mousedown",
  "mouseup",
  "mode_change",
  "node_tree_render_end",
  "rich_text_selection_change",
  "transforming-dom-to-images",
  "generalization_node_contextmenu",
  "painter_start",
  "painter_end",
  "scrollbar_change",
  "scale",
  "setData",
  "init"
] as const
type E = (typeof EventType)[number]

export default class MindMapUtil extends SingletonFactory<MindMapUtil>() {
  mindMap: MindMap | null = null
  currentId: string | null = null
  creating: boolean = false
  private event: Partial<Record<E, Function[]>> = {}
  $off(event: E, callback?: Function) {
    if (this.event[event]) {
      delete this.event[event]
      callback?.()
    }
  }
  $on(event: E, callback: Function) {
    if (this.event[event]) {
      this.event[event]?.push(callback)
    } else {
      this.event[event] = [callback]
    }
  }
  $emit(event: E, value?: any) {
    const e = this.event[event]
    if (e) {
      for (let i = 0; i < e.length; i++) {
        e[i](value)
      }
    }
  }
  manualSave() {
    const data = this.mindMap?.getData(true)
    if (data) {
      storeConfig(data)
    }
  }
  init(el: HTMLElement) {
    const { root, layout, theme, view, config } = getData()
    this.mindMap = new MindMap({
      el,
      data: {
        data: {
          text: "根节点"
        }
      },
      readonly: true,
      fit: false,
      layout,
      viewData: view,
      ...(config || {}),
      theme: theme.template,
      themeConfig: theme.config,
      initRootNodePosition: ["center", "center"],
      customInnerElsAppendTo: null,
      enableAutoEnterTextEditWhenKeydown: true,
      useLeftKeySelectionRightKeyDrag: true,
      customHandleClipboardText: handleClipboardText
      // handleIsSplitByWrapOnPasteCreateNewNode: () => {
      //   return this.$confirm(this.$t("edit.splitByWrap"), this.$t("edit.tip"), {
      //     confirmButtonText: this.$t("edit.yes"),
      //     cancelButtonText: this.$t("edit.no"),
      //     type: "warning"
      //   })
      // }
    })
    this.mindMap.keyCommand.addShortcut("Control+s", () => {
      this.manualSave()
    })
    this.mindMap.setThemeConfig({
      lineColor: "#009CE0",
      lineWidth: 3,
      lineStyle: "curve"
    })
    EventType.forEach((event) => {
      if (this.mindMap) {
        this.mindMap.on(event, (...args: any) => {
          this.$emit(event, args)
        })
      }
    })
    if (this.mindMap) {
      this.$on("setData", (data: any) => {
        console.log(data)
        if (data.root) {
          this.mindMap?.setFullData(data)
        } else {
          this.mindMap?.setData(data)
        }
        this.mindMap?.view.reset()
        this.manualSave()
      })
      this.$emit("init")
      this.$off("init")
    }
  }
  getTheme() {
    return this.mindMap?.getTheme()
  }
  setTheme(theme: any) {
    this.mindMap?.setTheme(theme)
  }
  createLineFromActiveNode() {
    if (this.mindMap) {
      this.mindMap.associativeLine.createLineFromActiveNode()
    }
  }
  export(type: string, fileName: string, withConfig: boolean, plusCssText?: string) {
    this.mindMap?.export(type, true, fileName, withConfig, plusCssText)
  }
  exec(name: E, value: any) {
    if (this.mindMap) {
      this.mindMap.execCommand(name, value)
    }
  }
  updateData(data: any) {
    if (this.mindMap) {
      this.mindMap.setData(data)
    }
  }
  copy() {
    if (this.mindMap) {
      const data = this.mindMap.getData(false)
      const text = `# ${data.data.text} \n\n`
      const children = data.children || []
      const formatString = (arr: [], depth = 0): string => {
        return (
          arr
            .map((item: any) => {
              if (depth === 0) {
                const prefix = `## ${item.data.text}`
                return prefix + "\n" + formatString(item.children, depth + 1)
              }

              const prefix = `${" ".repeat(depth + 1)} - ${item.data.text}`
              return prefix
            })
            .join("\n") + "\n"
        )
      }
      const result = text + formatString(children)
      clipboard(result)
    }
  }
  exportHtml(fileName = "mind-map") {
    if (this.mindMap) {
      const { svgHTML } = this.mindMap.getSvgData({ paddingX: 10, paddingY: 10 })
      const a = document.createElement("a")
      const html = createHtml(svgHTML)
      // 创建一个包含blob对象的url
      const url = window.URL.createObjectURL(
        new Blob([html], {
          type: ""
        })
      )
      a.href = url
      a.download = fileName + ".html"
      a.click()
      window.URL.revokeObjectURL(url)
    }
  }
  exportPicture(fileName = "mind-map") {
    if (this.mindMap) {
      this.mindMap.export("png", true, fileName)
    }
  }
}
